<?php
/**
 * Model for module/controller/action management in a admin area.
 * Also is used for permission validation. Example of data
 * 
 * module1
 * 		controller1
 * 			action1
 * 			action2
 * 			action3
 * 		controller2
 * 			action4
 * 			action5
 * 		controller3
 * 			action6
 * module2
 * 		controller4
 * 			action7
 * 
 * etc...
 * 	 
 * Tree algorithm is nested sets.
 * 
 * @author Konstantin Shamko <konstantin.shamko@gmail.com> 
 * @version 0.0.1
 * @copyright  Copyright (c) 2009 Konstantin Shamko
 * @category VaselinEngine
 * @package Usermanagement Module
 * @subpackage Model
 * @license  New BSD License
 *
 */
class Models_Usermanagement_Modules extends Bel_Model_Tree{
	/**
	 * Array of names of table classes which have one-to-many relations with modules table
	 *
	 * @var array
	 */	
	protected $_dependentTables = array ('Models_Usermanagement_Permissions');	
	/**
	 * Defines max depth level  
	 *
	 * @var integer
	 */
	protected $_maxlevel = 3;
	/**
	 * Constructor to set table with modules/controllers/actions 
	 * - name
	 * - primary key field name
	 * - level field name
	 * - left key field name
	 * - right key field name
	 * - array of the additional fields 
	 * 
	 * @return void
	 */
	public function __construct(){		
		$this->table = TABLE_PREFIX.'modules';
		$this->table_id = 'module_id';		
		$this->table_left = 'module_left_key';
		$this->table_right = 'module_right_key';
		$this->table_level = 'module_level';
		$this->table_add_fields = array('module_name','module_description');		
		parent::__construct();
	}
	/**
	 * Returns name of the primary key field
	 *
	 * @return string - name of the primary key field
	 */
	public function getTableId(){
		return $this->table_id;
	}
	/**
	 * Updates modules' record 
	 *
	 * @param integer $node_id - id of the entry to edit
	 * @param array $request - assosiative array with field=>value pairs
	 */
	public function editNode($node_id,$request){
		foreach ($this->table_add_fields as $field){
			$data[$field] = $request[$field];
		}
		$this->_db->update($this->table,$data,"module_id='$node_id'");
	}
	/**
	 * Returns all modules. Modules are stored with level  = 2
	 *
	 * @return array - array with modules
	 */
	public function getModules(){
		return parent::getTree($this->table_level."=2");
	}
	/**
	 * Returns controllers for specified module. Controllers are stored with level = 3
	 *
	 * @param integer $module_id - id of the module
	 * @return array - array with controllers 
	 */
	public function getControllersByModule($module_id){
		$data = $this->getTreeBranch($module_id,$this->table_level.'=3');
		return $data;
	}
	/**
	 * Returns actions for specified controller. Actions are stored with level = 4.
	 * If $group_id is defined elements assosiated with the specified group will be marked in the result. 
	 *
	 * @param integer $controller_id - id of the controller
	 * @param integer $group_id - id of the user group
	 * @return array - array with actions 
	 */
	public function getActionsByController($controller_id,$group_id=false){
		$data = $this->getTreeBranch($controller_id,$this->table_level.'=4');
		if($group_id){
			$permissions = new Models_Usermanagement_Permissions();
			for($i=0; $i<count($data);$i++){
				$data[$i]->perm = $permissions->getPermissionByGroupAndAction($group_id,$data[$i]->{$this->table_id});
			}
		}
		return $data;
	}
	/**
	 * Returns actions for specified module. Actions are stored with level = 4.
	 * If $group_id is defined elements assosiated with the specified group will be marked in the result. 
	 *
	 * @param integer $module_id - id of the module
	 * @param integer $group_id - id of the user group
	 * @return array - array with actions 
	 */
	public function getModuleActions($module_id,$group_id){
		$actions = $this->getTreeBranch($module_id);
		unset($actions[0]);
		$i=-1;

		$permissions = new Models_Usermanagement_Permissions();
		$data = array();
		if($actions){
			foreach($actions as $action){
				if($action->{$this->table_level}==3){
					$i++;
					$data[$i]=$action;
				}
	
				if($action->{$this->table_level}==4){
					$action->perm = $permissions->getPermissionByGroupAndAction($group_id,$action->{$this->table_id});
					$data[$i]->actions[]=$action;
				}
			}
		}
		return $data;
	}
	
	/**
	 * Returns array with resources (module:controller:action records) and flags which define if users from $group_id could get access to resourse
	 *
	 * @param integer $group_id - id of the users' group
	 * @return array - array with acl resources
	 */
	public function getAllAclResources($group_id){
		$select = $this->_db->select()
			->from($this->table)
			->joinLeft(TABLE_PREFIX.'permissions',$this->table.'.module_id='.TABLE_PREFIX.'permissions.module_id AND '.TABLE_PREFIX.'permissions.user_group_id=\''.$group_id.'\'',array('user_group_id'))
			->order($this->table_left);

		
		$actions = $this->_db->query($select)->fetchAll();
		unset($actions[0]);
			
		$resources = array();
		$i=1;
		$mod_contr = array();
		foreach($actions as &$action){			
			
			if($i>1 && $actions[$i-1]->module_level>$action->module_level){
				if($action->module_level==2){
					$mod_contr = array();
				}elseif($action->module_level==2){
					unset($mod_contr[1]);
				}
			}
			
			if(2 == $action->module_level){
				$mod_contr[0]=$action->module_name;
			}
			
			if(3 == $action->module_level){
				$mod_contr[1]=$action->module_name;
			}
						
			if(4 == $action->module_level){				
				$action->resource_name = implode(':',$mod_contr).':'.$action->module_name;
				$action->group = ($action->user_group_id)?$action->user_group_id:false;
				$resources[] = $action;
			}		
			
			$i++;
		}		
		return $resources;
	}
	
	
	/**
	 * Returns array with resources (module:controller:action records) and flags which define if users from $group_id could get access to resourse
	 *
	 * OLD VERSION WITH A LOT OF DB QUERIES!!!!
	 * 
	 * @param integer $group_id - id of the users' group
	 * @return array - array with acl resources
	 */
	/*public function getAllAclResources($group_id){
		$select = $this->_db->select()
			->from($this->table)
			->joinLeft(TABLE_PREFIX.'permissions',$this->table.'.module_id='.TABLE_PREFIX.'permissions.module_id AND '.TABLE_PREFIX.'permissions.user_group_id=\''.$group_id.'\'',array('user_group_id'))
			->where($this->table_level.'=4');
	
		$actions = $this->_db->query($select)->fetchAll();
		
		foreach($actions as &$action){
			$temp = $this->getParentBranch($action->module_id);
			unset($temp[0]);
			$str='';
			foreach ($temp as $t){
				$str.=$t->module_name.':';
			}
			$str = rtrim($str,':');
			$action->resource_name = $str;
			$action->group = ($action->user_group_id)?$action->user_group_id:false;
		}
		
		
		return $actions;
	}*/
	
	/**
	 * Returns controller by action id
	 *
	 * @param integer $action_id
	 * @return array with controller data
	 */
	public function getControllerByAction($action_id){
		return $this->getParentBranch($action_id,$this->table_level.'=3');
	}
	
	public function getModuleByName($module_name){
		return parent::getTree($this->table_level."=2 and module_name='$module_name'");
	}
}